import Vue from 'vue';
import _ from 'lodash';
import BaseModel from '../models/BaseModel.js';
import ListModel from '../models/ListModel.js';
import Util from './util.js';
import Services from './services';
import Lazyloader from './lazyloader';
import Framework from './framework';
import Dom7 from 'dom7';
import Formatter from './formatter.js';
import Config from '../config';

let loaders = Symbol("loaders");

class Controller {
    //#region 构造函数
    constructor() {
        this[loaders] = [];
        this.reload = true;
        this.vm = {};
        this.urls = {};
        this.context = {};
        this.queryType = 2;
        this.isBack = false; // 是否是返回页面，可判断当前页面是点击进来的还是返回来的
        this.res = {
            deleteConfirm: "确定要删除选择的记录吗？",
            deleteError: "删除失败！",
            deleteSuccess: "删除成功！",
            noSelectAtDeleting: "请先选择要删除的记录。",
            createError: "创建失败！",
            createSuccess: "创建成功！",
            updateError: "更新失败！",
            updateSuccess: "更新成功！"
        };
        this.listOptions = {
            groupFormat: undefined, //'第{0}～{1}项记录'
            searchKey: "allInLike"
        }
    }
    //#endregion

    //#region 属性
    //this.$$(this.$el.f7Page.$el,this.$el.f7Page.$navbarEl)
    get $ () {
        return (selector) => {
            if (selector instanceof Dom7 || _.isObject(selector)) {
                return selector;
            }
            let result = this.$$(this.$el).find(selector);
            if (this.vm.$theme.ios && this.$el.f7Page && this.$el.f7Page.$navbarEl) {
                let nresult = this.$$(this.$el.f7Page.$navbarEl).find(selector);
                if (nresult && nresult.length > 0) {
                    _.each(nresult, function (t) {
                        result.add(t);
                    });
                }
            }
            return result;
        };
    }
    get $$ () {
        return this.vm.$$;
    }
    get $el () {
        return this.vm.$el;
    }
    /**
     * @type {Framework}
     */
    get $framework () {
        return Vue.prototype.$framework;
    }
    get $f7 () {
        return Vue.prototype.$f7;
    }
    get $f7route () {
        return this.vm.$f7route;
    }
    get $data () {
        return this.context;
    }
    /**
     * @type {Util,_}
     * @returns {Util,_}
     */
    get $util () {
        return Util;
    }

    get $params () {
        return this.$f7route.query || {};
    }

    /**
     * @type {Formatter}
     */
    get $formatter () {
        return this.$framework.formatter;
    }
    //#endregion

    //#region 禁止重写方法
    polyfill (vm) {
        this.vm = vm;
        this.onInit();
        Services.setInstance("controller", vm.$f7route.path, this);
    }
    //#endregion

    //#region 初始化
    onBeforeInit () {
        this.buildContext();
    }
    onInit () {
        //overwrite
    }
    buildContext () {
        let models = new BaseModel();
        if (this.urls.query) {
            _.each(Util.buildArray(this.urls.query), (t, i) => {
                models = _.extend(models, new ListModel(i));
            });
        }
        if (this.mixin().data) {
            _.extend(models, this.mixin().data());
        }
        //Store.put("default", c);
        this.context = models;
        this.onBuildContext(models);
    }
    onBuildContext (models) {
        //overwrite
    }
    //#endregion

    //#region 加载数据，需要返回Promise，Promise的then方法会返回一个新的Promise实例
    getViewModel (conditions, preloader = true) {
        let enableProgress = this.enableProgress();
        if (enableProgress) {
            this.$f7.progressbar.show();
        }
        if (preloader) {
            this.$f7.preloader.show();
        }
        this.context.f7PageLoading = true;
        return new Promise((resolve, reject) => {
            let dc = this.disableCache();
            if (dc) {
                this.context = {};
                this.buildContext();
                this.onInit();
            }
            new Lazyloader(this, conditions).load(resolve, reject, preloader);
        }).then(() => {
            if (enableProgress) {
                this.$f7.progressbar.hide();
            }
            if (preloader) {
                this.$f7.preloader.hide();
            }
            this.context.f7PageLoading = false;
        }).catch(() => {
            if (enableProgress) {
                this.$f7.progressbar.hide();
            }
            if (preloader) {
                this.$f7.preloader.hide();
            }
        });
    }

    onBeforeQuery (type, conditions, params) { }

    /**
     * 调整数据
     *
     * 后台返回的viewModel里有search属性，而且可能search为空，导致把页面上的this.search的内容覆盖了
     * 所以该方法主要是调整类似该情况的响应数据，一般不用重写，如有需要可重写
     * @param {*} type 类型，model请求取值form, form$1, form$2 ... query请求取值list, list$1, list$2 ...
     * @param {*} isSuccess 请求是否成功
     * @param {*} result 该请求返回的数据
     */
    adaptData (type, isSuccess, result) {
        if (type == 'form' && result.search && this.$util.isEmpty(result.search)) {
            delete result.search;
        }
        return result;
    }
    onAfterQuery (type, isSuccess, result) {
        this.$$(".infinite-scroll-preloader").hide();
        return result;
    }
    onConvertItem (type, item) { }

    //#endregion

    //#region 数据绑定
    bind (data) {
        if (_.isArray(data)) {
            _.each(data, (t) => {
                _.extend(this.context, t);
            });
        } else {
            _.extend(this.context, data);
        }

        this.onBinded(data, this.context);
    }
    onBinded (data, context) { }
    //#endregion

    //#region 列表
    getLoader (type = "list") {
        return this[loaders][type];
    }
    setLoader (loader) {
        this[loaders][loader.getType()] = loader;
    }
    refresh (type, done) {
        this.getLoader(type).refresh().then((ret) => {
            if (ret === false) {
                return;
            }
            if (_.isFunction(done)) {
                done();
            } else {
                this.context.isRefresh = false;
            }
        });
    }
    infinite (type) {
        this.getLoader(type).infinite();
    }
    //#endregion

    //#region 搜索
    //(查询条件，类型)，类型：表单form，列表list\list$1\list$2
    searchQuery (value, type = "list") {
        if (type && type == "form") {
            value = value || {};
        } else if (_.isString(value)) {
            this.setSearch(this.listOptions.searchKey, value, type);
        } else {
            value = value || {};
            if (!this.$util.isEmpty(value)) {
                value = {
                    query: value
                };
            }
        }
        this.$f7.preloader.show();
        this.getLoader(type).query(_.isString(value) ? {} : value).then((values) => {
            this.bind(values);
            this.$f7.preloader.hide();
        }, (values) => {
            this.$f7.preloader.hide();
            if (!this.$f7.dialog.get()) {
                this.$f7.dialog.alert("请求失败，请稍后重试");
            }
            console.error(values);
        });
    }
    loopQuery (type) {
        this.getLoader(type).loopQuery();
    }
    setSearch (key, value, type) {
        var sKey = "search";
        if (type) {
            sKey += type.replace("list", "");
        }
        if (this.context[sKey] == undefined) {
            this.context[sKey] = {};
        }
        var inst = this.context[sKey];
        if (_.isString(value)) {
            value = _.toString(value);
        }
        inst[key] = value;
    }
    setSearchIfNull (key, value, type) {
        var sKey = "search";
        if (type) {
            sKey += type.replace("list", "");
        }
        if (this.context[sKey] == undefined) {
            this.setSearch(key, value, type);
        } else {
            var inst = this.context[sKey];
            if (inst[key] == undefined) {
                this.setSearch(key, value, type);
            }
        }
    }
    getSearch (key, type) {
        let sKey = "search";
        if (type) {
            sKey += type.replace("list", "");
        }
        if (this.context[sKey]) {
            return this.context[sKey][key];
        }
        return undefined;
    }
    //#endregion

    //#region 验证
    clearValidate (el = this.$el) {
        this.$$(el).find('input, textarea, select').each((index, inputEl) => {
            const $inputEl = this.$$(inputEl);
            if (!$inputEl.length) return;
            const $itemInputEl = $inputEl.parents('.item-input');
            const validity = $inputEl[0].validity;
            if (!validity) return;
            if (!validity.valid) {
                let $errorEl = $inputEl.nextAll('.item-input-error-message');
                $errorEl.remove();
                if ($errorEl.length > 0) {
                    $itemInputEl.removeClass('item-input-with-error-message');
                }
                $itemInputEl.removeClass('item-input-invalid');
                $inputEl.removeClass('input-invalid');
            }
        });
    }
    validate ($el = this.$el) {
        this.$f7.input.validateInputs($el);
        this.validatePicker();
        return this.$$($el).find('.item-input-invalid').length == 0;
    }
    validatePicker ($el = this.$el) {
        let $pels = this.$$($el).find('.f7-picker input[required]');
        if ($pels && $pels.length > 0) {
            this.$util.each($pels, t => {
                const inst = t.f7Picker;
                const $inputEl = this.$$(t);
                const $itemInputEl = $inputEl.parents('.item-input');
                if (inst && (!inst.getValue() || inst.getValue().length == 0)) {
                    const validationMessage = $inputEl.dataset().errorMessage || t.validationMessage || '请选择此字段。';
                    let $errorEl = $inputEl.nextAll('.item-input-error-message');
                    if (validationMessage) {
                        if ($errorEl.length === 0) {
                            $errorEl = this.$$('<div class="item-input-error-message"></div>');
                            $errorEl.insertAfter($inputEl);
                        }
                        $errorEl.text(validationMessage);
                    }
                    if ($errorEl.length > 0) {
                        $itemInputEl.addClass('item-input-with-error-message');
                    }
                    $itemInputEl.addClass('item-input-invalid');
                    $inputEl.addClass('input-invalid');
                } else {
                    this.$$(t).parents('.item-input').removeClass('item-input-invalid item-input-with-error-message');
                    this.$$(t).removeClass('input-invalid');
                }
            });
        }
        return this.$$($el).find('.item-input-invalid').length == 0;
    }
    //#endregion

    //#region 保存
    onBeforeSave (postModel) {
        return true;
    }
    save (postModel = this.context.models, url,msgTitle) {
        if (!url) {
            url = this.appendPrimaryKey(this.urls.save);
        }
        if (postModel == undefined || url == undefined) {
            this.afterSave(false, {
                message: 'PostModel或者URL不可为undefined'
            });
        } else {
            if (!this.validate()) {
                this.$f7.dialog.toast('请按提示填写必填项');
                return;
            }
            postModel = _.cloneDeep(postModel);
            postModel.pageAction = this.context.pageAction;
            if (this.onBeforeSave(postModel)) {
                this.$f7.preloader.show();
                this.$f7.request.postJSON(url, postModel, (r) => {
                    this.afterSave(r.success, r,msgTitle);
                    this.$f7.preloader.hide();
                }, (r) => {
                    this.afterSave(false, r,msgTitle);
                    this.$f7.preloader.hide();
                });
            }
        }
    }
    afterSave (isSuccess, result, msgTitle) {
        if (isSuccess && result.parameters && result.parameters.keys && this.context.pageAction == 'create') {
            this.context.pageAction = "edit";
            this.context.pageActionText = "编辑";
            this.context.primaryKey = result.parameters.keys;
        }
        this.$f7.dialog.alert(result.message || msgTitle || (isSuccess ? '提交成功' : '提交失败，请稍后重试'), () => {
            this.onAfterSave(isSuccess, result);
        });
    }
    onAfterSave (isSuccess, result) { }
    //#endregion

    //#region 删除
    onBeforeRemove (postModel) {
        return true;
    }
    onAfterRemove (isSuccess, result) { }
    afterRemove (isSuccess, result) {
        this.$f7.dialog.alert(result.message || (isSuccess ? this.res.deleteSuccess : this.res.deleteError), () => {
            this.onAfterRemove(isSuccess, result);
        });
    };
    remove (postModel = this.context.primaryKey, url = this.urls.remove) {
        if (postModel == undefined || url == undefined) {
            this.afterRemove(false, {
                message: 'PostModel或者URL不可为undefined'
            });
        } else {
            if (this.onBeforeRemove(postModel)) {
                this.$f7.dialog.confirm("确定删除嘛？", (r) => {
                    this.$f7.preloader.show();
                    postModel = _.isArray(postModel) ? postModel : [postModel];
                    this.$f7.request.postJSON(url, {
                        delete: JSON.stringify(postModel)
                    }, (r) => {
                        this.afterRemove(r.success, r);
                        this.$f7.preloader.hide();
                    }, (r) => {
                        this.afterRemove(false, r);
                        this.$f7.preloader.hide();
                    });
                });
            }
        }
    }
    //#endregion

    appendPrimaryKey (url) {
        if (!url) {
            return undefined;
        } else {
            let primaryKey = this.context.primaryKey || {};
            for (let o in primaryKey) {
                let v = primaryKey[o];
                if (v != undefined) {
                    let joinChar = url.indexOf("?") == -1 ? "?" : "&";
                    url += joinChar;
                    url += o + "=" + (primaryKey[o] || '');
                }
            }
            return url;
        }
    }

    // 添加其他数据
    appendData () {
        this.context.currentUser = vue.$f7.data.currentUser;
        // 让vue能够绑定该属性
        vue.$set(this.context, "allLoaded", false);
    }

    // 是否开启进度条，只有继承controller.js才会生效
    enableProgress() {
        //微前端基座存在不明原因无法关闭问题，暂时禁用
        return false;
    }

    // 返回页面时是否重新请求数据
    enableBackRequest () {
        return true;
    }

    // 是否禁用缓存，这里的缓存是指controller的缓存，
    // 每个页面的controller都是单例，进入同一个页面时controller的context还是上一次的数据
    disableCache () {
        return true;
    }

    // 是否禁用等待数据
    disableAwait () {
        return Config.setting.disableAwait || false;
    }

    //#region vue
    mixin () {
        return {};
    }
    //#endregion

    //#region 静态方法，vue-loader加载vue页面时如果发现页面有继承controller.js ，则都会调用default方法
    // 可在：项目目录/build/rules/vue-loader/lib/runtime/componentNormalizer.js 里打断点调试
    static get default () {
        return this.export({});
    }

    static
        export (options) {
        let instance = Services.getInstance(this);
        instance.onBeforeInit();
        if (!instance.context || Util.isEmpty(instance.context)) {
            instance.buildContext();
        }
        _.extend(options, instance.mixin());
        if (instance.mixins) {
            _.extend(options, instance.mixins);
        }
        options.controller = instance;
        options.queryType = instance.queryType;
        options.data = function () {
            // 追加其他数据，统一在appendData方法里写
            instance.appendData();
            return instance.context;
        };
        options.beforeCreate = function () {
            instance.vm = this;
            this.super = instance;
            if (instance.mixin().beforeCreate) {
                instance.mixin().beforeCreate.apply(instance.vm);
            }
        };
        options.created = function () {
            if (instance.mixin().created) {
                instance.mixin().created.apply(instance.vm);
            }
        };
        options.beforeMount = function () {
            if (instance.mixin().beforeMount) {
                instance.mixin().beforeMount.apply(instance.vm);
            }
        };
        options.mounted = function () {
            if (instance.mixin().mounted) {
                instance.mixin().mounted.apply(instance.vm);
            }
            instance.$$(".infinite-scroll-preloader").hide();
        };
        options.methods = _.extend({}, {
            getViewModel () {
                return instance.getViewModel();
            },
            save (postModel, url) {
                instance.save(postModel instanceof Event ? undefined : postModel, url);
            },
            send (postModel) {
                instance.send(postModel instanceof Event ? undefined : postModel);
            },
            remove (postModel) {
                if (postModel instanceof Event) {
                    instance.remove(this.primaryKey);
                } else {
                    instance.remove(postModel || this.primaryKey);
                }
            },
            refresh (done, event) {
                instance.context.allLoaded = false;
                if (event instanceof Event) {
                    instance.refresh(event.target.dataset.type, done);
                } else {
                    instance.refresh(event, done);
                }
            },
            infinite (e) {
                if (e instanceof Event) {
                    instance.infinite(e.target.dataset.type);
                } else {
                    instance.infinite(e);
                }
            },
            searchQuery (query, type) {
                instance.searchQuery(query, type);
            },
            loopQuery (query, type) {
                instance.loopQuery(query, type);
            },
            onSearch: function (searchbar, query) {
                // if (!searchbar._listen) {
                //     this.$$(searchbar.inputEl).on('compositionstart', function () {
                //         searchbar._end = false;
                //     });
                //     this.$$(searchbar.inputEl).on('compositionend', function () {
                //         searchbar._end = true;
                //         instance.searchQuery(this.value);
                //     });
                //     searchbar._listen = true;
                // }
                // if (searchbar._end) {
                //     instance.searchQuery(query);
                // }
                instance.searchQuery(query);
            },
            onReset: function () {
                instance.searchQuery('');
            },
            isListEmpty (type) {
                try {
                    let key = 'query';
                    if (type) {
                        key += type.replace('list', '');
                    }
                    return !instance.context[key] ||
                        !instance.context[key].data ||
                        instance.context[key].data.length == 0;
                } catch (e) {
                    console.error(e);
                }
                return false;
            },
            has (value, optionKey = 'key') {
                if (value != undefined && value.length > 0) {
                    return value.filter(item => {
                        return instance.$framework.account.hasPermission(item[optionKey]);
                    });
                }
                return [];
            },

            // 回到首页
            fnToHome () {
                instance.$framework.redirect.home()
            },
            // 获取工作流的相关参数
            getWorkflowArgs(params) {
              return new Promise((rs, rj) => {
                this.$f7.request.postJSON("/workflow/getWorkflowArgs", params, rlt => {
                  rs(rlt);
                }, e => {
                  rj(e);
                });
              });
            }
        }, options.methods);
        return options;
    }
    //#endregion
}
export default Controller;
